package com.cskaoyan.service;

import com.alibaba.druid.util.StringUtils;
import com.cskaoyan.bean.*;
import com.cskaoyan.bean.vo.AdminLogBo;
import com.cskaoyan.bean.vo.CarAndBrandVo;
import com.cskaoyan.bean.wx.vo.GoodsDetailCommentVo;
import com.cskaoyan.bean.wx.vo.GoodsDetailListData;
import com.cskaoyan.bean.wx.vo.GoodsDetailSpecificationListVo;
import com.cskaoyan.bean.wx.vo.IndexGoodsList;
import com.cskaoyan.mapper.*;
import com.cskaoyan.utils.DateUtils;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

@Service
public class GoodsServiceImpl implements GoodsService {

    @Autowired
    GoodsMapper goodsMapper;

    @Autowired
    CategoryMapper categoryMapper;

    @Autowired
    GoodsAttributeMapper goodsAttributeMapper;

    @Autowired
    GoodsSpecificationMapper goodsSpecificationMapper;

    @Autowired
    GoodsProductMapper goodsProductMapper;

    @Autowired
    IssueMapper issueMapper;

    @Autowired
    BrandMapper brandMapper;

    @Autowired
    CommentMapper commentMapper;

    @Autowired
    GrouponRulesMapper grouponRulesMapper;
    @Autowired
    CollectMapper collectMapper;
    @Autowired
    FootprintMapper footprintMapper;


    @Override
    public ListData<Goods> list(Integer page, Integer limit, String sort, String order, String goodsSn, String name) {
        //page页码
        //limit 当前页的大小
        PageHelper.startPage(page, limit);
        GoodsExample goodsExample = new GoodsExample();
        goodsExample.setOrderByClause(sort + " " + order);

        GoodsExample.Criteria criteria = goodsExample.createCriteria();

        //仅显示未被删除的商品
        criteria.andDeletedEqualTo(false);

        if (!StringUtils.isEmpty(goodsSn)) {
            criteria.andGoodsSnEqualTo(goodsSn);
        }
        if (!StringUtils.isEmpty(name)) {
            criteria.andNameLike("%" + name + "%");
        }

        List<Goods> goods = goodsMapper.selectByExample(goodsExample);
        PageInfo<Goods> goodsPageInfo = new PageInfo<>(goods);
        long total = goodsPageInfo.getTotal();
        ListData<Goods> listData = new ListData<>();
        listData.setTotal(total);
        listData.setItems(goods);
        return listData;
    }

    @Transactional
    @Override
    public void delete(Goods goods) {
        goods.setDeleted(true);
        goodsMapper.updateByPrimaryKeySelective(goods);

        GoodsAttributeExample goodsAttributeExample = new GoodsAttributeExample();
        GoodsProductExample goodsProductExample = new GoodsProductExample();
        GoodsSpecificationExample goodsSpecificationExample = new GoodsSpecificationExample();

        if (goods.getId() != null) {
            goodsAttributeExample.createCriteria().andGoodsIdEqualTo(goods.getId());
            goodsProductExample.createCriteria().andGoodsIdEqualTo(goods.getId());
            goodsSpecificationExample.createCriteria().andGoodsIdEqualTo(goods.getId());
        }

        List<GoodsAttribute> goodsAttributes = goodsAttributeMapper.selectByExample(goodsAttributeExample);
        List<GoodsProduct> goodsProducts = goodsProductMapper.selectByExample(goodsProductExample);
        List<GoodsSpecification> goodsSpecifications = goodsSpecificationMapper.selectByExample(goodsSpecificationExample);

        for (GoodsAttribute goodsAttribute : goodsAttributes) {
            goodsAttribute.setDeleted(true);
            goodsAttributeMapper.updateByPrimaryKey(goodsAttribute);
        }

        for (GoodsProduct goodsProduct : goodsProducts) {
            goodsProduct.setDeleted(true);
            goodsProductMapper.updateByPrimaryKey(goodsProduct);
        }

        for (GoodsSpecification goodsSpecification : goodsSpecifications) {
            goodsSpecification.setDeleted(true);
            goodsSpecificationMapper.updateByPrimaryKey(goodsSpecification);
        }
    }

    @Override
    public Map<String, List<CarAndBrandVo>> carAndBrand() {
        Map<String, List<CarAndBrandVo>> map = new HashMap<>();
        List<CarAndBrandVo> brandList = goodsMapper.queryBrandAllIdAndName();
        List<CarAndBrandVo> carList = goodsMapper.queryCatAllIdAndName();


        map.put("categoryList", carList);
        map.put("brandList", brandList);
        return map;
    }

    @Override
    public Map<String, Object> detail(Integer id) {

        Goods goods = goodsMapper.selectByPrimaryKey(id);

        Integer categoryId = goods.getCategoryId();
        Category category = categoryMapper.selectByPrimaryKey(categoryId);

        GoodsAttributeExample goodsAttributeExample = new GoodsAttributeExample();
        GoodsSpecificationExample goodsSpecificationExample = new GoodsSpecificationExample();
        GoodsProductExample goodsProductExample = new GoodsProductExample();
        if (goods.getId() != null) {
            goodsSpecificationExample.createCriteria().andGoodsIdEqualTo(goods.getId()).andDeletedEqualTo(false);
            goodsProductExample.createCriteria().andGoodsIdEqualTo(goods.getId()).andDeletedEqualTo(false);
            goodsAttributeExample.createCriteria().andGoodsIdEqualTo(goods.getId()).andDeletedEqualTo(false);
        }

        // attribute
        List<GoodsAttribute> goodsAttributes = goodsAttributeMapper.selectByExample(goodsAttributeExample);
        // specification
        List<GoodsSpecification> goodsSpecifications =
                goodsSpecificationMapper.selectByExample(goodsSpecificationExample);
        // product
        List<GoodsProduct> goodsProducts = goodsProductMapper.selectByExample(goodsProductExample);

        Map<String, Object> map = new HashMap<>();
        ArrayList<Integer> catIdsList = new ArrayList<>();
        catIdsList.add(category.getPid());
        catIdsList.add(categoryId);
        map.put("categoryIds", catIdsList);
        map.put("goods", goods);
        map.put("attributes", goodsAttributes);
        map.put("specifications", goodsSpecifications);
        map.put("products", goodsProducts);
        return map;
    }

    @Override
    public void create(Goods goods, List<GoodsAttribute> attributes, List<GoodsProduct> products, List<GoodsSpecification> specifications) {
        goods.setAddTime(DateUtils.getCurrentTime());
        goods.setUpdateTime(DateUtils.getCurrentTime());
        goods.setShareUrl("");
        goodsMapper.insertSelective(goods);

        Integer goodsId = goods.getId();

        for (GoodsAttribute attribute : attributes) {
            insertAttribute(attribute, goodsId);
        }

        for (GoodsProduct product : products) {
            insertProduct(product, goodsId);
        }

        for (GoodsSpecification specification : specifications) {
            insertSpecification(specification, goodsId);
        }
    }

    private void insertAttribute(GoodsAttribute attribute, Integer goodsId) {
        attribute.setAddTime(DateUtils.getCurrentTime());
        attribute.setUpdateTime(DateUtils.getCurrentTime());
        attribute.setGoodsId(goodsId);
        goodsAttributeMapper.insertSelective(attribute);
    }

    private void insertSpecification(GoodsSpecification specifications, Integer goodsId) {
        specifications.setAddTime(DateUtils.getCurrentTime());
        specifications.setUpdateTime(DateUtils.getCurrentTime());
        specifications.setGoodsId(goodsId);
        goodsSpecificationMapper.insertSelective(specifications);
    }

    private void insertProduct(GoodsProduct product, Integer goodsId) {
        product.setId(null);
        product.setAddTime(DateUtils.getCurrentTime());
        product.setUpdateTime(DateUtils.getCurrentTime());
        product.setGoodsId(goodsId);
        goodsProductMapper.insertSelective(product);
    }

    @Override
    public void update(Goods goods, List<GoodsAttribute> attributes, List<GoodsProduct> products, List<GoodsSpecification> specifications) {
        goods.setAddTime(null);
        goodsMapper.updateByPrimaryKey(goods);
        Integer goodsId = goods.getId();

        Map<String, Object> map = detail(goodsId);
        List<GoodsAttribute> attributesOld = (List<GoodsAttribute>) map.get("attributes");
        List<GoodsSpecification> specificationsOld = (List<GoodsSpecification>) map.get("specifications");

        updateAllAttribute(attributes, attributesOld, goodsId);
        updateAllProduct(products, goodsId);
        updateAllSpecification(specifications, specificationsOld, goodsId);
    }

    @Override
    public Long countGoods() {
        long l = goodsMapper.countByExample(null);
        return l;
    }

    private void updateAllProduct(List<GoodsProduct> products, Integer goodsId) {
        // 1、删除原有product相关的数据 (修改deleted的值为true)
        GoodsProductExample goodsProductExample = new GoodsProductExample();
        // 添加条件:指定商品的id、delete指定为false表示只修改未被删除的状态的记录
        goodsProductExample.createCriteria().andGoodsIdEqualTo(goodsId).andDeletedEqualTo(false);
        GoodsProduct record = new GoodsProduct();
        record.setDeleted(true);
        goodsProductMapper.updateByExampleSelective(record, goodsProductExample);

        // 2、将新的数据进行插入
        for (GoodsProduct product : products) {
            insertProduct(product, goodsId);
        }
    }

    private void updateAllSpecification(List<GoodsSpecification> specificationsNew, List<GoodsSpecification> specificationsOld, Integer goodsId) {
        Map<Integer, Boolean> map = new HashMap<>();
        for (GoodsSpecification specification : specificationsOld) {
            map.put(specification.getId(), true);
        }
        for (GoodsSpecification specification : specificationsNew) {
            if (specification.getId() != null) {
                map.put(specification.getId(), false);
            } else {
                // 新插入的部分
                insertSpecification(specification, goodsId);
            }

        }
        Set<Map.Entry<Integer, Boolean>> entries = map.entrySet();
        for (Map.Entry<Integer, Boolean> entry : entries) {
            GoodsSpecification specification = new GoodsSpecification();
            specification.setId(entry.getKey());
            if (entry.getValue().equals(true)) {
                specification.setDeleted(true);
                goodsSpecificationMapper.updateByPrimaryKeySelective(specification);
            } else if (entry.getValue().equals(false)) {
                specification.setUpdateTime(DateUtils.getCurrentTime());
                goodsSpecificationMapper.updateByPrimaryKeySelective(specification);
            }
        }

    }

    private void updateAllAttribute(List<GoodsAttribute> attributesNew, List<GoodsAttribute> attributesOld, Integer goodsId) {
        HashMap<Integer, Boolean> map = new HashMap<>();
        for (GoodsAttribute attribute : attributesOld) {
            map.put(attribute.getId(), true);
        }
        for (GoodsAttribute attribute : attributesNew) {
            if (attribute.getId() != null) {
                map.put(attribute.getId(), false);
            } else {
                insertAttribute(attribute, goodsId);
            }
        }
        Set<Map.Entry<Integer, Boolean>> entries = map.entrySet();
        for (Map.Entry<Integer, Boolean> entry : entries) {
            GoodsAttribute attribute = new GoodsAttribute();
            attribute.setId(entry.getKey());
            if (entry.getValue().equals(true)) {
                attribute.setDeleted(true);
                goodsAttributeMapper.updateByPrimaryKeySelective(attribute);
            } else if (entry.getValue().equals(true)) {
                attribute.setUpdateTime(DateUtils.getCurrentTime());
                goodsAttributeMapper.updateByPrimaryKeySelective(attribute);
            }
        }
    }

    @Override
    public Category selectCurrentCategory(Integer id) {
        Category category = categoryMapper.selectByPrimaryKey(id);
        return category;
    }

    @Override
    public Category selectParentCategory(Integer id) {
        Integer pid = categoryMapper.selectPid(id);
        Category category = categoryMapper.selectByPrimaryKey(pid);
        return category;
    }

    @Override
    public List<Category> selectBrotherCategory(Integer id) {
        Integer pid = categoryMapper.selectPid(id);
        CategoryExample categoryExample = new CategoryExample();
        CategoryExample.Criteria criteria = categoryExample.createCriteria();
        criteria.andPidEqualTo(pid);
        List<Category> categories = categoryMapper.selectByExample(categoryExample);
        return categories;
    }


    @Override
    public HashMap<String, Object> selectGoodsList(Integer categoryId, Integer page, Integer size) {
        PageHelper.startPage(page, size);
        List<IndexGoodsList> goodsLists =goodsMapper.selectGoodsLists(categoryId);
        PageInfo<IndexGoodsList> goodsPageInfo = new PageInfo<>(goodsLists);
        long total = goodsPageInfo.getTotal();
        HashMap<String, Object> map = new HashMap<>();
        map.put("count",total);
        map.put("goodsList" ,goodsLists);
        return map;
    }

    @Override
    public List<IndexGoodsList> selectRelatedGoodsList(Integer id) {
        List<IndexGoodsList> goodsLists =goodsMapper.selectRelatedGoodsList(id);
        return goodsLists;
    }

    @Override
    public HashMap<String, Object> wxGoodsDetail(Integer id) {
        HashMap<String, Object> map = new HashMap<>();
        //attribute
        GoodsAttributeExample goodsAttributeExample = new GoodsAttributeExample();
        goodsAttributeExample.createCriteria().andGoodsIdEqualTo(id).andDeletedEqualTo(false);
        List<GoodsAttribute> goodsAttributes = goodsAttributeMapper.selectByExample(goodsAttributeExample);
        //brand  先获取商品的brand_id 根据其去获取brand表信息
        Integer brandId = goodsMapper.selectBrandId(id);
        Brand brand = brandMapper.selectByPrimaryKey(brandId);
        //comment
        PageHelper.startPage(1,5);
        GoodsDetailListData comment = new GoodsDetailListData();
        List<GoodsDetailCommentVo> commentList= commentMapper.selectComment(id);
        comment.setData(commentList);
        PageInfo<GoodsDetailCommentVo> adminPoPageInfo = new PageInfo<GoodsDetailCommentVo>(commentList);
        long count = adminPoPageInfo.getTotal();
        comment.setCount(count);
        map.put("comment",comment);
        //groupon
        GrouponRulesExample grouponRulesExample = new GrouponRulesExample();
        grouponRulesExample.createCriteria().andDeletedEqualTo(false).andGoodsIdEqualTo(id);
        List<GrouponRules> grouponRules = grouponRulesMapper.selectByExample(grouponRulesExample);
        map.put("groupon",grouponRules);
        //info
        Goods info = goodsMapper.selectByPrimaryKey(id);
        map.put("info",info);

        //issue
        IssueExample issueExample = new IssueExample();
        issueExample.createCriteria().andDeletedEqualTo(false);
        List<Issue> issues = issueMapper.selectByExample(issueExample);
        //productList
        GoodsProductExample goodsProductExample = new GoodsProductExample();
        goodsProductExample.createCriteria().andGoodsIdEqualTo(id).andDeletedEqualTo(false);
        List<GoodsProduct> productList = goodsProductMapper.selectByExample(goodsProductExample);
        map.put("productList",productList);
        //shareImage
        String shareImage=goodsMapper.selectShareImages(id);
        map.put("shareImage",shareImage);

        //specificationList
        List<GoodsDetailSpecificationListVo> specificationList =goodsSpecificationMapper.selectSpecificationList(id);
        map.put("specificationList",specificationList);
        //userHasCollect
        Subject subject = SecurityUtils.getSubject();
        Integer userId = (Integer) subject.getPrincipal();
        Integer status = collectMapper.selectHasCollect(userId,id);
        if (status!=null && status.equals(0)) {
            status = 1 ;
        }else{
            status = 0;
        }
        map.put("userHasCollect",status);


        map.put("attribute",goodsAttributes);
        map.put("brand",brand);
        map.put("issue",issues);
        // 加入足迹
        FootprintExample footprintExample = new FootprintExample();
        FootprintExample.Criteria criteria = footprintExample.createCriteria();
        criteria.andUserIdEqualTo(userId).andGoodsIdEqualTo(id);
        List<Footprint> footprints = footprintMapper.selectByExample(footprintExample);
        if (footprints.size()==1){
            footprints.get(0).setAddTime(new Date());
            footprintMapper.updateByPrimaryKeySelective(footprints.get(0));
        }else {
            Footprint footprint = new Footprint(null,userId,id,new Date(),new Date(),false);
            footprintMapper.insert(footprint);
        }
        return map;
    }

    @Override
    public Integer selectSonCategoryId(Integer id) {
        Integer ids = goodsMapper.selectSonCategoryId(id);
        return ids;
    }

    @Override
    public String selectLevel(Integer id) {
        String level = goodsMapper.selectLevel(id);
        return level;
    }
}
